package main

import (
	"context"
	"fmt"
	"sync"
	"time"
)

var wg sync.WaitGroup

// 中断取消子channel的方法
// 1. 监控全局变量
// 2 通过 channel
//var stop bool
//  两种方案并不统一
// go 1.7+ context 支持

//var stop chan bool = make(chan bool)

//func cpuInfo() {
//	defer wg.Done()
//
//	for {
//		select {
//		case <-stop:
//			fmt.Println("退出CPU监控")
//			return // 后面无法运行到
//		default:
//			time.Sleep(time.Second * 2)
//			fmt.Println("cpu 信息读取完成 ")
//		}
//
//	}
//}

// 父的 context
// 父的context 被取消，父的context 生成的子context 也会被取消
func cpuInfo(ctx context.Context) {
	defer wg.Done()
	ctx2, _ := context.WithCancel(ctx)
	//go memInfo(ctx) // 嵌套的子channel 调用 // 往下传
	go memInfo(ctx2)
	for {
		select {
		case <-ctx.Done():
			fmt.Println("监控 cpu 退出")
			return
		default:
			time.Sleep(time.Second)
			fmt.Println("获取 cpu 信息成功")
		}

	}

}

func memInfo(ctx context.Context) {
	defer wg.Done()
	for {
		select {
		case <-ctx.Done():
			fmt.Println("监控 mem 退出")
			return
		default:
			time.Sleep(time.Second)
			fmt.Println("获取 mem 信息成功")
		}

	}

}

func main() {

	//启动
	wg.Add(2)
	//ctx, cancel := context.WithCancel(context.Background())  // 手动关闭
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) //  支持默认取消，和手动取消

	//context.WithDeadline()
	//context.WithTimeout()
	//context.WithValue()

	go cpuInfo(ctx)
	//go memInfo(ctx) // 传递同一个ctx 也可以取消
	//time.Sleep(time.Second * 6)
	//stop = true
	//stop <- true
	//cancel()

	time.Sleep(time.Second * 1)
	cancel()

	wg.Wait()
	fmt.Println("信息监控完成")

}
